package com.wj.core.net;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;

import com.wj.core.common.client.IClient;
import com.wj.core.dto.Request;
import com.wj.core.dto.Response;
import com.wj.core.serialize.Serializer;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.UUID;

/**
 * @author: wangjun
 * @create: 2018-06-05 
 **/
public class NetClientProxy implements FactoryBean<Object>, InitializingBean {

  private static final Logger logger = LoggerFactory.getLogger(NetClientProxy.class);

  private String serverAddress;
  private NetEnum netEnum = NetEnum.NETTY;
  private Serializer serializer;
  public Class<?> interfaceClass;
  private long timeoutMills = 5000;

  public NetClientProxy() {
  }

  public NetClientProxy(final String serverAddress, final NetEnum netEnum, final Serializer serializer,
      final Class<?> interfaceClass,
      final long timeoutMills) {
    this.serverAddress = serverAddress;
    this.netEnum = netEnum;
    this.serializer = serializer;
    this.interfaceClass = interfaceClass;
    this.timeoutMills = timeoutMills;
  }

  @Override
  public Object getObject() throws Exception {
    return Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), new Class[]{interfaceClass},
        new InvocationHandler() {
          @Override
          public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable {
            Request request = new Request();
            request.setRequestId(UUID.randomUUID().toString());
            request.setCreateMillisTime(System.currentTimeMillis());
            request.setMethodName(method.getName());
            request.setServiceImplName(method.getDeclaringClass().getName());
            request.setParameters(args);
            request.setParameterTypes(method.getParameterTypes());

            Response response = client.sendMsg(request);

            if (response == null) {
              logger.info("wj-rpc response was null");
              throw new IllegalArgumentException("wj-rpc response was null");
            }
            if (response.getError() != null) {
              throw response.getError();
            } else {
              return response.getData();
            }
          }
        });
  }

  @Override
  public Class<?> getObjectType() {
    return null;
  }

  IClient client = null;

  @Override
  public void afterPropertiesSet() throws Exception {
    client = netEnum.clientClass.newInstance();
    client.init(serverAddress, serializer, timeoutMills);
  }
}
